/**
 * Copyright (c) 2016 Lenovo Group
 * All Rights Reserved.
 * 
 * Project Name:assign-tracer
 * Create Time: 2016年4月27日 下午4:18:58
 */
package com.lenovo.lmrp.server.assigntracer.scheduler;

import java.text.MessageFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lenovo.lmrp.api.model.entity.AssigningTicketPO;
import com.lenovo.lmrp.api.model.entity.TicketPO;
import com.lenovo.lmrp.api.model.entity.TicketSystemPO;
import com.lenovo.lmrp.base.event.EventCode;
import com.lenovo.lmrp.base.event.EventContent;
import com.lenovo.lmrp.base.event.EventSource;
import com.lenovo.lmrp.base.event.EventTopic;
import com.lenovo.sdc.framework.dao.ADaoFactory;
import com.lenovo.sdc.framework.dao.ICommonDAO;
import com.lenovo.sdc.framework.dao.ICommonDAO.FinderEnum;
import com.lenovo.sdc.framework.mq.AMQClient;
import com.lenovo.sdc.framework.scheduler.ACommonTask;
import com.lenovo.sdc.framework.scheduler.Schedule;
import com.lenovo.sdc.framework.util.AttributeBean;
import com.lenovo.sdc.framework.util.CommonUtil;
import com.lenovo.sdc.framework.util.JSONHelper;
import com.lenovo.sdc.framework.util.exception.ErrorCode;
import com.lenovo.sdc.framework.util.exception.TraceableException;

/**
 * @author zhangzheng
 *
 */
public class ScanExceptionalTicketTask extends ACommonTask {
    
    private static final Logger logger = LoggerFactory.getLogger(ScanExceptionalTicketTask.class);
    
    private String taskID;
    private ADaoFactory daoFactory;
    private AttributeBean params;
    private Schedule schedule;
    private AMQClient mqClient;
    
    public ScanExceptionalTicketTask(AMQClient mqClient,ADaoFactory daoFactory,AttributeBean params) {
        this.mqClient = mqClient;
        this.daoFactory = daoFactory;
        this.schedule = new Schedule(params.getAttribute("exceptional.scan.interval", 3600));
        this.params = params;
        this.taskID = "scanexceptionalticket:" + System.nanoTime();
    }
    
    @Override
    public String getID() {
        return taskID;
    }

    @Override
    public Schedule getSchedule() {
        return schedule;
    }

    @Override
    public void execute() throws Exception {
        try (ICommonDAO dao = daoFactory.createDAO()) {
            logger.debug("task {} scan exceptional tickets started.",this.taskID);
            //抢单扩散时间 单位分钟
            String retryInterval = System.getProperty("RETRY_INTERVAL", "10");
            //抢单扩散次数
            int groups = params.getAttribute("group.number", 1);
            //扩散总分钟数  再延长5分钟
            int overMinute = groups * Integer.valueOf(retryInterval) + 5;
            Calendar calendar = Calendar.getInstance();
            calendar.add(Calendar.MINUTE, 0 - overMinute);
            Date starttime = calendar.getTime();
            //查找超时没人处理的工单列表
            String sql1  = "select id,ticketid as ticketId,engineerid as engineerId,assignpolicy as assignPolicy "
                            + " from {0}.itsm_assigning_ticket "
                            + " where notifytime < ?";
            //查找由于MQ失败导致的工作流创建失败的工单
            String sql2 = "select a.id,a.caption,a.projectid as projectId"
                            + ",a.customerid as customerId,a.assignee,a.priority"
                            + ",a.severity,a.createtime as createTime,a.creater"
                            + ",a.updatetime as updateTime,a.description,a.status"
                            + ",a.latitude,a.longitude,a.starttime as startTime"
                            + " from {0}.itsm_ticket a"
                            + " left join {1}.itsm_assigning_ticket b on a.id = b.ticketid"
                            + " left join lmrp.lmrp_ticket_process c on a.id = c.ticketid and c.status <> 2"
                            + " where b.ticketid is null "
                            + " and c.ticketid is null "//没有有效的工作流实例
                            + " and a.status in (0,1)";//待接单or待抢单
            
            Map<String, List<AssigningTicketPO>> overTimeTickets = new HashMap<>();
            Map<String, List<TicketPO>> noWorkflowTickets = new HashMap<>();
            List<TicketSystemPO> systems = dao.filteByCondition(TicketSystemPO.class, null);
            for (TicketSystemPO ts : systems) {
                //查找超时没人处理的工单列表
                try {
                    if (CommonUtil.nonNullAndEmpty(ts.getItsmCode())) {
                        List<AssigningTicketPO> tickets = dao.getRegisteredFinder(FinderEnum.SQL).findMappedRecord(MessageFormat.format(sql1, ts.getItsmCode()), AssigningTicketPO.class, new Object[]{starttime});
                        if (tickets.size() > 0) {
                            overTimeTickets.put(ts.getItsmCode(), tickets);
                        }
                    }
                }
                catch (Exception exp) {
                    TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "failed seach over time tickets from itsmsystem:" + ts.getItsmCode(), exp);
                    continue;
                }
                //查找由于MQ失败导致的工作流创建失败的工单
                try {
                    if (CommonUtil.nonNullAndEmpty(ts.getItsmCode())) {
                        List<TicketPO> pos = dao.getRegisteredFinder(FinderEnum.SQL).findMappedRecord(MessageFormat.format(sql2, ts.getItsmCode(),ts.getItsmCode()), TicketPO.class, new Object[]{});
                        if (pos.size() > 0) {
                            noWorkflowTickets.put(ts.getItsmCode(), pos);
                        }
                    }
                }
                catch (Exception exp) {
                    TraceableException.writeLog(ErrorCode.DB_QUERY_FAILED, "failed seach no workflow tickets from itsmsystem:" + ts.getItsmCode(), exp);
                    continue;
                }
            }
            //mq发送
            if (!overTimeTickets.keySet().isEmpty()) {
                EventContent<Map<String, List<AssigningTicketPO>>> content = new EventContent<>();
                content.setSource(EventSource.TRACER);
                content.setCode(EventCode.EXCEPTION_TICKET_OVERTIME);
                content.setContent(overTimeTickets);
                mqClient.publish(EventTopic.EXCEPTION.name(), JSONHelper.toJSON(content));
                logger.debug("task {} send mq content {}",this.taskID,JSONHelper.toJSON(content));
                logger.debug("task {} scan over time tickets ended.",this.taskID);
            }
            //mq发送
            if (!noWorkflowTickets.keySet().isEmpty()) {
                EventContent<Map<String, List<TicketPO>>> content = new EventContent<>();
                content.setSource(EventSource.TRACER);
                content.setCode(EventCode.EXCEPTION_TICKET_NOWORKFLOW);
                content.setContent(noWorkflowTickets);
                mqClient.publish(EventTopic.EXCEPTION.name(), JSONHelper.toJSON(content));
                logger.debug("task {} send mq content {}",this.taskID,JSONHelper.toJSON(content));
                logger.debug("task {} scan no workflow tickets ended.",this.taskID);
            }
        }
        catch (Exception exp) {
            TraceableException.writeLog(ErrorCode.DB_ERROR, "failed scan exceptional tickets", exp);
        }
    }

}
